# -*- coding: utf-8 -*-
import struct
import re
__all__ = ("read_cardinfo", "Card", "read_dec", "read_Expan")
__doc__ = """
Reads Apprentice compatible resource files.
"""
__license__ = "MIT License <http://www.opensource.org/licenses/mit-license.php>"
__copyright__ = "2005, Tiago Cogumbreiro"
__author__ = "Tiago Cogumbreiro <cogumbreiro@users.sf.net>"

def read_short (stream):
    count = stream.read (2)
    count, = struct.unpack ("H", count)
    return count

def read_byte (stream):
    count = stream.read (1)
    count, = struct.unpack ("B", count)
    return count

def read_int (stream):
    count = stream.read (4)
    count, = struct.unpack ("I", count)
    return count
    
def read_string (stream):
    return unicode(stream.read (read_short (stream)), "windows-1252").encode ("utf-8")

def read_cardinfo (stream):
    """
    Parses 'cardinfo.dat'.
    
    Returns an iterator that yields a dictionary of the fields found.
    The keys used are:
    ['color', 'cost', 'expansions', 'flavor', 'name', 'power', 'toughness',
     'text', 'type', 'rarity']
    
    """
    next_int    = lambda: read_int (stream)
    next_string = lambda: read_string (stream)
    next_short  = lambda: read_short (stream)
    next_byte   = lambda: read_byte (stream)
    
    location = next_int ()
    stream.seek (location)

    cards_count = next_int ()
    
    card = {}
    while cards_count > 0:
        
        card["name"] = next_string ()
        next_location = next_int ()
        card["color"] = next_byte ()
        expansions, rarity = next_string ().split ("-")
        card["expansions"] = expansions.split (",")
        card["rarity"] = rarity
        stream.read (2)
        
        prev_location = stream.tell ()

        stream.seek (next_location)

        card["type"] = next_string ()
        card["cost"] = next_string ()
        card["power"] = None
        card["toughness"] = None
        
        power_toughness = next_string ().split ("/")
        if len (power_toughness) == 2:
            card["power"], card["toughness"] = power_toughness
            
        card["text"] = next_string ()
        card["flavor"] = next_string ()
        
        stream.seek (prev_location)
        
        yield card
        
        cards_count -= 1
    
def read_Expan (stream):
    """
    Parses 'Expan.dat' files, this contains the name of the
    rarity and expansion ID's.
    
    This function returns an iterator which yields a tuple with
    three elements:
        - the id
        - the english name
    """
    expansions = []
    for line in stream.readlines ():
        # Remove trailling \n\r
        line = line.strip("\n\r")
        id = line[0:2]
        
        if id.startswith("-"):
            continue
            
        name = line[3:]
        
        yield id, name
    
def read_dec (stream):
    """
    Parses .dec files
    """
    main_deck = {}
    sideboard_deck = {}
    
    sb_re  = re.compile ("SB: +([0-9]+) +(.+)\n")
    main_re = re.compile ("([0-9]+) +(.+)\n")
    
    for line in stream.readlines ():
        
        
        mobj = sb_re.match (line)
        deck = sideboard_deck
        
        if mobj is None:
            mobj = main_re.match (line)
            deck = main_deck
             
            if mobj is None:
                continue

        quantity = int (mobj.group (1))
        name = unicode(mobj.group (2), "utf-8")

        name = name.replace (u"'", u"’")
        
        if name not in deck:
            deck[name] = quantity
        else:
            deck[name] += quantity

    return main_deck, sideboard_deck

RARITIES = {
    "C": "Common",
    "R": "Rare",
    "P": "Promotional",
    "U": "Uncommon",
    "S": "Special",
}


def read_database (expan_stream, cardinfo_stream):
    global RARITIES
    
    for expansion in read_Expan (expan_stream):
        Expansion (code = expansion[0], name = expansion[1])
        
    #expansions = dict(tuple(iter(read_Expan (expan_stream))))
    
    
    for row in read_cardinfo (cardinfo_stream):
        if row['rarity'] == '':
            row['rarity'] = 'C'
            
        row['rarity'] = RARITIES[row['rarity']]
        
        expansions = row["expansions"]
        del row["expansions"]
        row["card_type"] = row["type"]
        del row["type"]
        
        card = Card (**row)
        for expansion in expansions:
            exp = list(Expansion.select (Expansion.q.code == expansion))
            if len (exp) == 0:
                exp = Expansion (code = expansion, name = expansion)
            else:
                exp = exp[0]
                
            card.addExpansion (exp)
            
from sqlobject import *

class Card (SQLObject):
    color = IntCol()
    cost = StringCol ()
    flavor = StringCol ()
    name = StringCol ()
    power = StringCol ()
    toughness = StringCol ()
    text = StringCol()
    card_type = StringCol ()
    rarity = StringCol ()
    expansions = RelatedJoin ("Expansion")
     
class Expansion (SQLObject):
    name = StringCol ()
    code = StringCol ()
    cards = RelatedJoin ("Card")

import gtk
import gobject

class CardModel (gtk.GenericTreeModel):
    Cols = (gobject.TYPE_INT,) + (gobject.TYPE_STRING,) * 8 + (gobject.TYPE_PYOBJECT,)
    ColsAttrs = ("color", "cost", "flavor", "name", "power", "toughness", "text",
                 "card_type", "rarity", "expansions")
    Model = Card
    
    total = None
    def __init__ (self):
        self.update_query ()
        gtk.GenericTreeModel.__init__ (self)
        
    def update_query (self,  *args, **kwargs):
        self._query = list(self.Model.select (*args, **kwargs))
        self.invalidate_iters()
        
    def on_get_flags(self):
        return gtk.TREE_MODEL_LIST_ONLY
    
    def on_get_n_columns(self):
        return len (self.Cols)
        
    def on_get_column_type (self, index):
        return self.Cols[index]
    
    def on_get_iter (self, path):
        return path
    
    def on_get_value (self, node, column):
        #row = self.Model.get (node[0] + 1)
        row = self._query[node[0]]
        return getattr (row, self.ColsAttrs[column])
    
    def on_iter_next (self, node):
        node = node[0]
            
        if node == len (self._query) - 1:
            return None
        
        return (node + 1,)
    
    def on_iter_children (self, node):
        if node is None:
            return (0,)
        
        return None
    
    def on_iter_has_child (self, node):
        return False
    
    def on_iter_n_children (self, node):
        if len (node) == 1:
            return len (self.Cols)
        
        return 0
   
    def on_iter_nth_child (self, node, n):
        if node is None:
            return (n,)
        return None
        
    def on_iter_parent (self, node):
        if len (node) == 0:
            return None
        else:
            return node[:-1]

class Demo(gtk.Window):
    def __init__(self, parent=None):
        gtk.Window.__init__(self)
        try:
            self.set_screen(parent.get_screen())
        except AttributeError:
            self.connect('destroy', lambda *w: gtk.main_quit())
        self.set_title(self.__class__.__name__)
        vbox = gtk.VBox ()
        vbox.show ()
        self.add (vbox)
        
        scrolled_window = gtk.ScrolledWindow()
        scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        vbox.add(scrolled_window)
        
        btn = gtk.Button ("Search")
        btn.connect ("clicked", self.on_clicked)
        btn.show ()
        vbox.pack_start (btn, fill = False, expand = False)
        
        self.rarities = ("Common", "Uncommon", "Rare", "Promotional")
        self.curr_rarity = 0
        
        
        self.model = model = CardModel()
        
        tree_view = gtk.TreeView(model)
        cell = gtk.CellRendererText()
        # the text in the column comes from column 0
        column = gtk.TreeViewColumn("Name", cell, text=3)
        tree_view.append_column(column)

        scrolled_window.add(tree_view)
        self.show_all()            
    
    def on_clicked (self, *args):
        self.model.update_query (Card.q.rarity == self.rarities[self.curr_rarity])
        self.curr_rarity += 1
        self.curr_rarity %= len (self.rarities)

if __name__ == '__main__':
    import os
    import os.path
    import sys
    
    db_filename = os.path.join (os.getcwd(), "mtg.db")
    connection_string = "sqlite:" + db_filename
    connection = connectionForURI (connection_string)
    sqlhub.processConnection = connection
    Demo ()
    gtk.main()
    sys.exit()
    
    Card.createTable ()
    Expansion.createTable ()
    
    fd1 = open (".mindless/Expan.dat")
    fd2 = open (".mindless/cardinfo.dat")
    
    #for card in read_Expan (fd):
    #for card in read_cardinfo (fd):
    
    for card in read_database (fd1, fd2):
        #print card
        pass
    fd1.close ()
    fd2.close ()
    #import sys
    #fd = open (sys.argv[1])
    #for name in read_dec (fd)[1]:
    #    print name
    #fd.close ()
    
